import Canvas2DBase from "./Canvas2DBase";
import {TreeLine, TreeNode, String2D, TreeNode_R} from "./Canvas2DItem";

class Tree2D extends Canvas2DBase{
  constructor(width, height){
    super(width, height);
    this.type="Tree2D";

    this.initTree2D();
  }

  initTree2D(){
    this.addAttribute('nodeSize', 24, 'number', '结点');
    this.addAttribute('nodeBgColor', '#00f000', 'color', '结点');
    this.addAttribute('nodeColor', '#000000', 'color', '结点');

    // const root = new TreeNode(this.width/2, this.nodeSize + parseInt(this.paddingY), '(1,2)');
    // const left = new TreeNode(this.width/2 - this.nodeSize * 2, this.nodeSize*4 + parseInt(this.paddingY), '(2,3)');
    // this.items.push(root);
    // this.items.push(left);
    // const line = new TreeLine(this.width/2, this.nodeSize + parseInt(this.paddingY),
    //   this.width/2 - this.nodeSize * 2, this.nodeSize*4 + parseInt(this.paddingY));
    // this.items.push(line);
  }

  addNode(x, y, name){
    const newNode = new TreeNode(x, y, name);
    this.items.push(newNode);
  }
  addLine(x1, y1, x2, y2){
    const newLine = new TreeLine(x1, y1, x2, y2);
    this.items.push(newLine);
  }
  addNode_R(x, y, name){
    const newNode = new TreeNode_R(x, y, name);
    this.items.push(newNode);
  }
  addstring(str, x, y, font, fontSize, fill=true, color=[0,0,0]){
    const newString = new String2D(str, x, y, font, fontSize, fill, color);
    this.items.push(newString)
  }

}

class deep{
  constructor(tree){
    this.max=1
    this.width_ = 0
  }

  get_depth(tree){
    let that = this
    that.max = 1
    that.width_ = 0
    var rev = that.get_depth_(tree, that.max)
    return rev
  }
  
  get_depth_(tree, depth=1){
    let that = this
    for(var key in tree){
      var d = depth
      if((Object.keys(tree).length == 1))
      {
        if(d>that.max){
          that.max=d
        }
        that.width_++
      }
      else if(key!='node'){
        d++
        that.get_depth_(tree[key], d)
      }
    }
    return {"a":that.max, "b":that.width_}
  }
}

function drawDecisionTree(element, node){
  if(!element) return;
  if(!node) return;
  const tree = new Tree2D(100, 100);
  const dd = new deep()
  const nodeSize = tree.nodeSize;
  var rev = dd.get_depth(node)
  const depth = rev.a
  const width = rev.b * 3;

  const th = depth * nodeSize * 5;
  const tw = width * nodeSize * 6;
  tree.width = tw;
  tree.height = th;

  // 添加根
  let x = tw / 2;
  let y = nodeSize * 2;
  drawDecisionChild(tree, node, x, y);

  element.appendChild(tree.domElement);
  tree.update();
}

function drawDecisionChild(tree, child, x, y){
  const dd = new deep()
  var l = Object.keys(child).length
  if(l < 1) return;
  var i=0
  for(var key in child){
    if(key!='node'){
      if(i!=(l-1) || l<3 ){
        let node = child[key];
        var rev = dd.get_depth(node)
        let w = Math.pow(1.8,(rev.a-1)) * tree.nodeSize * Math.pow(1.3,l-1) * Math.pow(1.2,Object.keys(child[key]).length);
        tree.addLine(x, y, x - w + 1.5*w/(l-2.001)*(i-1) , y + tree.nodeSize * 4);
        tree.addstring(key, (x+(x - w + 1.5*w/(l-2.001)*(i-1)))/2 - Math.pow(1.5, key.length) * 15 , (y+(y + tree.nodeSize * 4))/2)
        // console.log(key);
        drawDecisionChild(tree, node, x - w + 1.5*w/(l-2.001)*(i-1), y + tree.nodeSize * 4);
      }
      else{
        let node = child[key];
        var rev = dd.get_depth(node)
        let w = Math.pow(1.8,(rev.a-1)) * tree.nodeSize * Math.pow(1.3,l-1) * Math.pow(1.2,Object.keys(child[key]).length);
        tree.addLine(x, y, x - w + 1.5*w/(l-2.001)*(i-1), y + tree.nodeSize * 4);
        tree.addstring(key, (x+(x - w + 1.5*w/(l-2.001)*(i-1)))/2 + 10 , (y+(y + tree.nodeSize * 4))/2)
        // console.log(key);
        drawDecisionChild(tree, node, x - w + 1.5*w/(l-2.001)*(i-1), y + tree.nodeSize * 4);
      }
    }
    else{
      var rev = dd.get_depth(child)
      if(rev.a<2){
        tree.addNode_R(x, y, child['node']);
      }
      else{
        tree.addNode(x, y, child['node']);
      }
    }
    i++
  } 
}

function drawKDTree(element, node){
  if(!element) return;
  if(!node) return;
  const tree = new Tree2D(100, 100);
  const nodeSize = tree.nodeSize;
  const depth = node.getDepth();
  const width = Math.pow(2, depth - 1);

  const th = depth * nodeSize * 5;
  const tw = width * nodeSize * 6;
  tree.width = tw;
  tree.height = th;

  // 添加根
  let x = tw / 2;
  let y = nodeSize * 2;
  drawKDChild(tree, node, x, y);

  element.appendChild(tree.domElement);
  tree.update();
}

function drawKDChild(tree, child, x, y){
  if(!child) return;
  tree.addNode(x, y, child.name());

  if(child.left){
    let node = child.left;
    let w = Math.pow(2, node.getDepth()) * tree.nodeSize * 1.5;

    tree.addLine(x, y, x - w , y + tree.nodeSize * 4);
    drawKDChild(tree, child.left, x - w, y + tree.nodeSize * 4);
  }
  if(child.right){
    let node = child.right;
    let w = Math.pow(2, node.getDepth()) * tree.nodeSize * 1.5;
    tree.addLine(x, y, x + w, y + tree.nodeSize * 4);
    drawKDChild(tree, child.right, x + w, y + tree.nodeSize * 4);
  }
}

export default Tree2D;
export {drawKDTree, drawDecisionTree};